package com.want.controller;

import com.want.model.dto.Result;
import com.want.model.dto.ResultUtil;
import com.want.models.entity.Role;
import com.want.models.entity.UserRoleBo;
import com.want.repository.RoleRepository;
import com.want.repository.UserRoleRepository;
import com.want.req.base.PageReqDto;
import com.want.req.user.dto.LoginReqDto;
import com.want.req.user.dto.RegisterReqDto;
import com.want.req.user.dto.UpdateUserReqDto;
import com.want.resp.base.PageResp;
import com.want.resp.user.dto.*;
import com.want.service.UserService;
import com.want.util.MyBeanUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * @author WangZhiJian
 * @since 2021/11/21
 */
@RestController("user")
public class UserController {
    @Resource
    private UserService userService;
    @Resource
    private UserRoleRepository userRoleRepository;
    @Resource
    private RoleRepository roleRepository;

    @PostMapping("saveUser")
    public Mono<Result<RegisterRespDto>> saveUser(@RequestBody RegisterReqDto registerReqDto){
        return userService.save(registerReqDto);
    }

    @PostMapping("updateUser")
    public Mono<Result<Integer>> updateUser(@RequestBody UpdateUserReqDto updateUserReqDto){
        return userService.update(updateUserReqDto);
    }

    @GetMapping("findById")
    public Mono<Result<UserDto>> findById(Integer id){
        return userService.selectById(id);
    }

    @PostMapping(value = "listUser")
    public Mono<Result<PageResp<UserDto>>> listUser(@RequestBody PageReqDto pageReqDto){
        return userService.listUser(pageReqDto)
                .zipWith(userService.count())
                .map(tuple2 ->{
                    Long total = tuple2.getT2();
                    long pages = total%pageReqDto.getSize() == 0 ? total/pageReqDto.getSize() : total/pageReqDto.getSize() +1;
                    return PageResp.<UserDto>builder().pages(pages).total(total).result(tuple2.getT1()).build();
                }).map(ResultUtil::ofSuccess);
    }

    @PostMapping("login")
    public Mono<Result<LoginRespDto>> login(@RequestBody @Validated LoginReqDto loginReqDto){
        return userService.login(loginReqDto);
    }

    @GetMapping("userRole/{id}")
    public Mono<Result<List<String>>> userRole(@PathVariable("id") Integer uid){
        return userRoleRepository.findByUid(Arrays.asList(uid),UserRoleBo.class)
                .map(UserRoleBo::getName)
                .collectList()
                .map(ResultUtil::ofSuccess)
                .switchIfEmpty(Mono.defer(() -> Mono.just(ResultUtil.ofSuccess(Collections.emptyList()))));
    }

    @GetMapping("userRole/delete/{id}")
    public Mono<Result<String>> delete(@PathVariable("id") Integer uid){
        return userService.deleteByIdOrEmail(uid,null);
    }

    @GetMapping("userInfo")
    public Mono<Result<UserInfoDto>> userInfo(Integer id){
        return userService.userInfo(id);
    }

    @GetMapping("roleList")
    public Mono<Result<List<RoleDto>>> roleList(){
        return roleRepository.findAll()
                .collectList()
                .map(list -> list.stream().map(role -> MyBeanUtil.copyProperties(role, RoleDto.class)).collect(toList()))
                .map(ResultUtil::ofSuccess);
    }

    @PostMapping("role/add")
    public Mono<Result<RoleDto>> createRole(@RequestBody RoleDto roleDto){
        return roleRepository.save(MyBeanUtil.copyProperties(roleDto, Role.class))
                .map(role -> MyBeanUtil.copyProperties(role, RoleDto.class))
                .map(ResultUtil::ofSuccess);
    }

    @GetMapping("role/delete/{id}")
    public Mono<Result<Integer>> deleteRole(@PathVariable("id") Integer id){
        return roleRepository.deleteById(id)
                .then(Mono.just(1))
                .map(ResultUtil::ofSuccess);
    }

}
